﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Drawing;
using System.Drawing.Imaging;
using System.IO;

namespace Project_02
{
    class Report {
        private class FontPrint {
            private Font  font;
            private Brush brush;
            private Byte  size;
            public FontPrint(Font font, Brush brush) {
                this.font = font;
                this.brush = brush;
                this.size = Convert.ToByte(font.SizeInPoints);
            }
            public Font Font {
                get { return font; }
            }
            public Brush Brush {
                get { return brush; }
            }
            public Byte Size {
                get { return size; }
            }
        }
        private FontPrint titleFont;
        private FontPrint textFont;
        private Color     backgroundColor;
        private Point     position;
        public class Title {
            private String name;
            private List<Column> column;
            public Title(String name, List<Column> column) {
                this.name = name;
                this.column = column;
            }
            public String Name {
                get { return name; }
            }
            public List<Column> Column {
                get { return column; }
            }
        }
        public class Column {
            private String name;
            private String value;
            public Column(String name, String value) {
                this.name = name;
                this.value = value;
            }
            public String Name {
                get { return name; }
            }
            public String Value {
                get { return value; }
            }
        }
        public Report(List<Title> list) {
            titleFont       = new FontPrint(new Font("Courier New", 18, FontStyle.Bold), new SolidBrush(Color.FromArgb(0x61, 0x94, 0xBC)));
            textFont        = new FontPrint(new Font("Courier New", 14), new SolidBrush(Color.FromArgb(0x60, 0x60, 0x60)));
            backgroundColor = Color.White;
            position        = new Point(10, 0);
            GetReport(list);
        }
        private void GetReport(List<Title> list) {
            System.IO.Directory.CreateDirectory(@"Data\\Reports");
            String file      = @"Data\\Reports\\" + String.Format("report_{0:yyyyMMddHHmmss}.png", DateTime.Now);
            Size size        = new Size(640, GetRequiredHeight(list));
            Bitmap bitmap    = new Bitmap(size.Width, size.Height);
            bitmap.SetResolution(72, 72);
            Graphics graphic = Graphics.FromImage(bitmap);
            graphic.Clear(backgroundColor);
            Size colSize = GetColumnSize(list, graphic);
            DrawWatermark(@"Data\\Image\\logo.png", size, graphic);
            foreach (Title title in list) {
                DrawTitle(title.Name, size, graphic);
                foreach (Column column in title.Column) {
                    DrawColumn(column.Name, column.Value, colSize, graphic);
                }
            }
            bitmap.Save(file);
            graphic.Dispose();
            bitmap.Dispose();
            System.Diagnostics.Process.Start(file);
        }
        private void DrawColumn(String column, String value, Size size, Graphics graphic) {
            if (column.Length > 0) {
                StringFormat format = new StringFormat();
                format.Alignment = StringAlignment.Far;
                graphic.DrawString(column, textFont.Font, textFont.Brush, (RectangleF)new Rectangle(position.X + 10, position.Y, size.Width + 5, size.Height), format);
                graphic.DrawString(value, textFont.Font, textFont.Brush, position.X + size.Width + 40, position.Y);
            } else {
                graphic.DrawString(value, textFont.Font, textFont.Brush, position.X + 10, position.Y);
            }
            position.Y += textFont.Size + 2;
        }
        private void DrawTitle(String title, Size size, Graphics graphic) {
            position.Y += 10;
            graphic.DrawString(title, titleFont.Font, titleFont.Brush, position.X, position.Y);
            graphic.DrawLine(new Pen(titleFont.Brush, 2), 13, position.Y + titleFont.Size + 3, size.Width - 13, position.Y + titleFont.Size + 3);
            position.Y += titleFont.Size + 3 + 5;
        }
        private void DrawWatermark(String file, Size size, Graphics graphic) {
            ImageAttributes attributes = new ImageAttributes();
            //inverting the colors, setting transparency to 50%
            float[][] colorMatrixElements = { 
               new float[] {-1.0f,  0.0f,  0.0f,  0.0f,  0.0f},
               new float[] { 0.0f, -1.0f,  0.0f,  0.0f,  0.0f},
               new float[] { 0.0f,  0.0f, -1.0f,  0.0f,  0.0f},
               new float[] { 0.0f,  0.0f,  0.0f,  0.2f,  0.0f},
               new float[] { 1.0f,  1.0f,  1.0f,  0.0f,  1.0f}
            };
            ColorMatrix colorMatrix = new ColorMatrix(colorMatrixElements);
            attributes.SetColorMatrix(colorMatrix, ColorMatrixFlag.Default, ColorAdjustType.Bitmap);
            //rotate the image
            Image image = Image.FromFile(file);
            Bitmap bitmap = new Bitmap(size.Width, size.Height);
            Graphics g = Graphics.FromImage(bitmap);
            g.RotateTransform(45.0f);
            for (Int32 index = 0; index < size.Height / (image.Width / 1.5f); ++index) { //
                g.DrawImage(image, image.Height + image.Width * index / 2, -image.Height + image.Width * index / 2);
            }
            graphic.DrawImage(bitmap, new Rectangle(0, 0, size.Width, size.Height), 0, 0, size.Width, size.Height, GraphicsUnit.Pixel, attributes);
        }
        private Int32 GetRequiredHeight(List<Title> list) {
            Int32 height = 20;
            foreach (Title title in list) {
                height += titleFont.Size + 10 + 3 + 5 + title.Column.Count * (textFont.Size + 2);
            }
            return height;
        }
        private Size GetColumnSize(List<Title> list, Graphics graphic) {
            Size size = new Size(0, 0);
            foreach (Title title in list) {
                foreach (Column column in title.Column) {
                    SizeF sizef = graphic.MeasureString(column.Name, textFont.Font);
                    if (sizef.Width > size.Width) size.Width = Convert.ToByte(sizef.Width);
                    if (sizef.Height > size.Height) size.Height = Convert.ToByte(sizef.Height);
                }
            }
            return size;
        }
    }
}
